﻿namespace YidanSoft.Library.EditorUtility.CommandBars
{
    using System;
    using System.Collections;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using YidanSoft.Library.EditorUtility.Collections;
    using YidanSoft.Library.EditorUtility.General;
    using YidanSoft.Library.EditorUtility.Win32;

    public class ReBar : Control, IMessageFilter
    {
        private RebarBandCollection bands = new RebarBandCollection();
        private bool bGotIsCommonCtrl6 = false;
        private bool isCommonCtrl6 = false;
        private static bool needsColorUpdate = false;

        public ReBar()
        {
            base.SetStyle(ControlStyles.UserPaint, false);
            base.TabStop = false;
            this.Dock = DockStyle.Top;
            this.bands.Changed += new EventHandler(this.Bands_Changed);
        }

        private void Band_HandleCreated(object s, EventArgs e)
        {
            this.ReleaseBands();
            Control control = (Control) s;
            this.UpdateBand(this.bands.IndexOf(control));
            this.CaptureBands();
        }

        private void Band_TextChanged(object s, EventArgs e)
        {
            Control control = (Control) s;
            this.UpdateBand(this.bands.IndexOf(control));
        }

        private void Bands_Changed(object s, EventArgs e)
        {
            this.UpdateBands();
        }

        private void BeginUpdate()
        {
            WindowsAPI.SendMessage(base.Handle, 11, 0, 0);
        }

        private void CaptureBands()
        {
            foreach (Control control in this.bands)
            {
                control.HandleCreated += new EventHandler(this.Band_HandleCreated);
                control.TextChanged += new EventHandler(this.Band_TextChanged);
            }
        }

        protected override void CreateHandle()
        {
            if (!base.RecreatingHandle)
            {
                YidanSoft.Library.EditorUtility.Win32.INITCOMMONCONTROLSEX icc = new YidanSoft.Library.EditorUtility.Win32.INITCOMMONCONTROLSEX();
                icc.dwSize = Marshal.SizeOf(typeof(YidanSoft.Library.EditorUtility.Win32.INITCOMMONCONTROLSEX));
                icc.dwICC = 0x404;
                bool flag = WindowsAPI.InitCommonControlsEx(icc);
            }
            base.CreateHandle();
        }

        protected override void Dispose(bool disposing)
        {
            this.bands.Changed -= new EventHandler(this.Bands_Changed);
        }

        private void DrawGripper(Graphics g, Rectangle bounds)
        {
            bounds.X = bounds.Left - 7;
            bounds.Width = 7;
            g.FillRectangle(new SolidBrush(ColorUtil.VSNetControlColor), bounds);
            int height = bounds.Height;
            for (int i = 2; i < (height - 1); i++)
            {
                if (ColorUtil.UsingCustomColor)
                {
                    g.DrawLine(new Pen(ColorUtil.VSNetBorderColor, 1f), bounds.Left, bounds.Top + i, bounds.Left + 3, bounds.Top + i);
                }
                else
                {
                    g.DrawLine(new Pen(SystemColors.ControlDark, 1f), bounds.Left, bounds.Top + i, bounds.Left + 3, bounds.Top + i);
                }
                i++;
            }
        }

        private void EndUpdate()
        {
            WindowsAPI.SendMessage(base.Handle, 11, 1, 0);
        }

        private int GetBandActualIndex(int bandIndex)
        {
            return this.GetRebarInfo(bandIndex).wID;
        }

        private REBARBANDINFO GetBandInfo(int index)
        {
            Control control = this.bands[index];
            REBARBANDINFO rebarbandinfo = new REBARBANDINFO();
            rebarbandinfo.cbSize = Marshal.SizeOf(typeof(REBARBANDINFO));
            if (!this.IsCommonCtrl6())
            {
                rebarbandinfo.fMask = 2;
                rebarbandinfo.clrBack = (int) ColorUtil.RGB(ColorUtil.VSNetControlColor.R, ColorUtil.VSNetControlColor.G, ColorUtil.VSNetControlColor.B);
                rebarbandinfo.clrFore = (int) ColorUtil.RGB(0xff, 0, 0xff);
            }
            rebarbandinfo.iImage = 0;
            rebarbandinfo.hbmBack = IntPtr.Zero;
            rebarbandinfo.lParam = 0;
            rebarbandinfo.cxHeader = 0;
            rebarbandinfo.fMask |= 0x100;
            rebarbandinfo.wID = index;
            if ((control.Text != null) && (control.Text != string.Empty))
            {
                rebarbandinfo.fMask |= 4;
                rebarbandinfo.lpText = Marshal.StringToHGlobalAnsi(control.Text);
                rebarbandinfo.cch = (control.Text == null) ? 0 : control.Text.Length;
            }
            rebarbandinfo.fMask |= 1;
            rebarbandinfo.fStyle = 0xa4;
            ToolBarEx ex = (ToolBarEx) control;
            if (ex.UseNewRow)
            {
                rebarbandinfo.fStyle |= 1;
            }
            rebarbandinfo.fStyle |= (control is IChevron) ? 0x200 : 0;
            rebarbandinfo.fMask |= 0x10;
            rebarbandinfo.hwndChild = control.Handle;
            rebarbandinfo.fMask |= 0x20;
            rebarbandinfo.cyMinChild = control.Height;
            rebarbandinfo.cxMinChild = 0;
            rebarbandinfo.cyChild = 0;
            rebarbandinfo.cyMaxChild = 0;
            rebarbandinfo.cyIntegral = 0;
            rebarbandinfo.fMask |= 0x40;
            rebarbandinfo.cx = control.Width;
            rebarbandinfo.fMask |= 0x200;
            rebarbandinfo.cxIdeal = control.Width;
            return rebarbandinfo;
        }

        public Rectangle GetBandRect(int bandIndex)
        {
            YidanSoft.Library.EditorUtility.Win32.RECT lParam = new YidanSoft.Library.EditorUtility.Win32.RECT();
            int bandActualIndex = this.GetBandActualIndex(bandIndex);
            WindowsAPI.SendMessage(base.Handle, 0x409, bandIndex, ref lParam);
            return new Rectangle(lParam.left, lParam.top, lParam.right - lParam.left, lParam.bottom - lParam.top);
        }

        public int GetRebarHeight()
        {
            return (WindowsAPI.SendMessage(base.Handle, 0x41b, 0, 0) + 1);
        }

        private REBARBANDINFO GetRebarInfo(int index)
        {
            REBARBANDINFO lParam = new REBARBANDINFO();
            lParam.cbSize = Marshal.SizeOf(typeof(REBARBANDINFO));
            lParam.fMask = 0x300;
            WindowsAPI.SendMessage(base.Handle, 0x41c, index, ref lParam);
            return lParam;
        }

        protected bool HitGripper(MouseEventArgs e)
        {
            Point pt = new Point(e.X, e.Y);
            Control control = null;
            for (int i = 0; i < this.bands.Count; i++)
            {
                control = this.bands[i];
                Rectangle bounds = control.Bounds;
                bounds.X = bounds.Left - 7;
                bounds.Width = 7;
                if (bounds.Contains(pt))
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsCommonCtrl6()
        {
            if (!this.bGotIsCommonCtrl6)
            {
                YidanSoft.Library.EditorUtility.Win32.DLLVERSIONINFO dvi = new YidanSoft.Library.EditorUtility.Win32.DLLVERSIONINFO();
                dvi.cbSize = Marshal.SizeOf(typeof(YidanSoft.Library.EditorUtility.Win32.DLLVERSIONINFO));
                WindowsAPI.GetCommonControlDLLVersion(ref dvi);
                this.bGotIsCommonCtrl6 = true;
                this.isCommonCtrl6 = dvi.dwMajorVersion >= 6;
            }
            return this.isCommonCtrl6;
        }

        private void NotifyChevronPushed(ref Message m)
        {
            NMREBARCHEVRON lParam = (NMREBARCHEVRON) m.GetLParam(typeof(NMREBARCHEVRON));
            int uBand = lParam.uBand;
            int wID = this.GetRebarInfo(uBand).wID;
            Control control = this.bands[wID];
            Point point = new Point(lParam.rc.left, lParam.rc.bottom);
            (control as IChevron).Show(this, point);
        }

        private void NotifyChildSize()
        {
            for (int i = 0; i < this.bands.Count; i++)
            {
                ((ToolBarEx) this.bands[i]).ToolbarSizeChanged();
            }
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            this.RealizeBands();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (this.HitGripper(e))
            {
                base.Capture = true;
                if (this.ShowMoveCursor(e))
                {
                    Cursor.Current = Cursors.SizeAll;
                }
                else
                {
                    Cursor.Current = Cursors.VSplit;
                }
            }
            else
            {
                Cursor.Current = Cursors.Default;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (!base.Capture)
            {
                if (this.HitGripper(e))
                {
                    if (this.ShowMoveCursor(e))
                    {
                        Cursor.Current = Cursors.SizeAll;
                    }
                    else
                    {
                        Cursor.Current = Cursors.SizeWE;
                    }
                }
                else
                {
                    Cursor.Current = Cursors.Default;
                }
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            bool flag = this.HitGripper(e);
            base.Capture = false;
            if (flag)
            {
                if (this.ShowMoveCursor(e))
                {
                    Cursor.Current = Cursors.SizeAll;
                }
                else
                {
                    Cursor.Current = Cursors.SizeWE;
                }
            }
            else
            {
                Cursor.Current = Cursors.Default;
            }
        }

        protected override void OnParentChanged(EventArgs e)
        {
            if (base.Parent != null)
            {
                Application.AddMessageFilter(this);
            }
            else
            {
                Application.RemoveMessageFilter(this);
            }
        }

        private void PaintBackground()
        {
            int num;
            ToolBarEx ex;
            if (needsColorUpdate)
            {
                needsColorUpdate = false;
                for (num = 0; num < this.bands.Count; num++)
                {
                    ex = (ToolBarEx) this.bands[num];
                    ex.UpdateToolBarItems();
                }
                for (num = 0; num < this.bands.Count; num++)
                {
                    this.UpdateBand(num);
                }
            }
            if (!this.IsCommonCtrl6())
            {
                Control control = null;
                for (num = 0; num < this.bands.Count; num++)
                {
                    Graphics g = base.CreateGraphics();
                    control = this.bands[num];
                    RectangleF clipBounds = g.ClipBounds;
                    Rectangle bounds = control.Bounds;
                    if (clipBounds.Contains(bounds))
                    {
                        ex = (ToolBarEx) this.bands[num];
                        if (ex.BarType == BarType.MenuBar)
                        {
                            Rectangle bandRect = this.GetBandRect(num);
                            int num2 = ((bandRect.Height - bounds.Height) / 2) - 1;
                            bounds = new Rectangle(bounds.Left, bounds.Top - num2, bandRect.Width, bandRect.Height - 2);
                        }
                        this.DrawGripper(g, bounds);
                    }
                    g.Dispose();
                }
            }
        }

        public override bool PreProcessMessage(ref Message msg)
        {
            foreach (Control control in this.bands)
            {
                if (control.PreProcessMessage(ref msg))
                {
                    return true;
                }
            }
            return false;
        }

        private void RealizeBands()
        {
            this.ReleaseBands();
            this.BeginUpdate();
            for (int i = 0; i < this.bands.Count; i++)
            {
                REBARBANDINFO bandInfo = this.GetBandInfo(i);
                WindowsAPI.SendMessage(base.Handle, 0x40a, i, ref bandInfo);
            }
            this.UpdateSize();
            this.EndUpdate();
            this.CaptureBands();
        }

        private void ReleaseBands()
        {
            foreach (Control control in this.bands)
            {
                control.HandleCreated -= new EventHandler(this.Band_HandleCreated);
                control.TextChanged -= new EventHandler(this.Band_TextChanged);
            }
        }

        private bool ShowMoveCursor(MouseEventArgs e)
        {
            Point pt = new Point(e.X, e.Y);
            Control control = null;
            for (int i = 0; i < this.bands.Count; i++)
            {
                control = this.bands[i];
                Rectangle bounds = control.Bounds;
                bounds.X = bounds.Left - 7;
                bounds.Width = 7;
                if (bounds.Contains(pt) && (bounds.Left <= 5))
                {
                    return true;
                }
            }
            return false;
        }

        bool IMessageFilter.PreFilterMessage(ref Message message)
        {
            IntPtr ptr;
            ArrayList list = new ArrayList();
            for (ptr = base.Handle; ptr != IntPtr.Zero; ptr = WindowsAPI.GetParent(ptr))
            {
                list.Add(ptr);
            }
            for (ptr = message.HWnd; ptr != IntPtr.Zero; ptr = WindowsAPI.GetParent(ptr))
            {
                Msg msg = (Msg) message.Msg;
                if (list.Contains(ptr))
                {
                    return this.PreProcessMessage(ref message);
                }
            }
            return false;
        }

        public void UpdateBackgroundColor()
        {
            for (int i = 0; i < this.bands.Count; i++)
            {
                this.UpdateBand(i);
                ((ToolBarEx) this.bands[i]).Invalidate();
            }
            base.Invalidate();
        }

        private void UpdateBand(int index)
        {
            if (base.IsHandleCreated)
            {
                this.BeginUpdate();
                int bandActualIndex = this.GetBandActualIndex(index);
                REBARBANDINFO bandInfo = this.GetBandInfo(bandActualIndex);
                int idealSize = ((ToolBarEx) this.bands[bandActualIndex]).GetIdealSize();
                bandInfo.cxIdeal = idealSize;
                WindowsAPI.SendMessage(base.Handle, 0x40b, index, ref bandInfo);
                this.UpdateSize();
                this.EndUpdate();
            }
        }

        private void UpdateBands()
        {
            if (base.IsHandleCreated)
            {
                base.RecreateHandle();
            }
        }

        public static void UpdateBandsColors(object sender, EventArgs e)
        {
            needsColorUpdate = true;
        }

        private void UpdateSize()
        {
            base.Height = WindowsAPI.SendMessage(base.Handle, 0x41b, 0, 0) + 1;
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            switch (m.Msg)
            {
                case 15:
                    this.PaintBackground();
                    break;

                case 0x4e:
                case 0x204e:
                {
                    YidanSoft.Library.EditorUtility.Win32.NMHDR lParam = (YidanSoft.Library.EditorUtility.Win32.NMHDR) m.GetLParam(typeof(YidanSoft.Library.EditorUtility.Win32.NMHDR));
                    switch (lParam.code)
                    {
                        case -841:
                            this.NotifyChevronPushed(ref m);
                            break;

                        case -839:
                            this.NotifyChildSize();
                            break;

                        case -831:
                            this.UpdateSize();
                            break;
                    }
                    break;
                }
            }
        }

        public RebarBandCollection Bands
        {
            get
            {
                return this.bands;
            }
        }

        protected override System.Windows.Forms.CreateParams CreateParams
        {
            get
            {
                System.Windows.Forms.CreateParams createParams = base.CreateParams;
                createParams.ClassName = "ReBarWindow32";
                createParams.Style = 0x56000000;
                createParams.Style |= 0x48;
                createParams.Style |= 0x2200;
                return createParams;
            }
        }

        protected override Size DefaultSize
        {
            get
            {
                return new Size(100, 0x2c);
            }
        }
    }
}

